package com.leaf.u_spring.chapter11;

import javax.sql.DataSource;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Repository;

/**
 * JPA配置
 */
@Configuration
public class PersistenceConfig {

	/**
	 * 应用程序管理
	 * @return
	 */
	@Bean
	public LocalEntityManagerFactoryBean entityManagerFactoryBean(){
		LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
		//persistence.xml文件必须位于类路径下的META-INF目录下，作用是定义一个或多个持久化单元
		emfb.setPersistenceUnitName("");
		return emfb;
	}
	
	/**
	 * 容器管理
	 * @return
	 */
	@Bean
	public LocalContainerEntityManagerFactoryBean containerEntityManagerFactoryBean(
			DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
		LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
		//任意javax.sql.DataSource的实现的都可以，优先级比persistence.xml配置文件高
		emfb.setDataSource(dataSource);	
		//jpaVendorAdapter属性用于指明所使用的是哪一个厂商的JPA实现
		emfb.setJpaVendorAdapter(jpaVendorAdapter);
		//设置识别持久化单元中的实体类的包路径，查找带有@Entity注解的类
		emfb.setPackagesToScan("com.leaf");
		return emfb;
	}
	
	/**
	 * JPA的实现
	 * 	HibernateJpaVendorAdapter
		EclipseJpaVendorAdapter
		OpenJpaVendorAdapter
	 * @return
	 */
	@Bean
	public JpaVendorAdapter jpaVendorAdapter(){
		HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
		adapter.setDatabase(Database.HSQL);
		adapter.setShowSql(true);
		adapter.setGenerateDdl(false);
		adapter.setDatabasePlatform("org.hibernate.dialect.HSQLDialect");
		return adapter;
	}
	
	/**
	 * 从JNDI获取实体管理器工厂
	 * JndiObjectFactoryBean是FactoryBean接口的实现，能够创建EntityManagerFactory
	 * @return
	 */
	@Bean
	public JndiObjectFactoryBean jndiObjectFactoryBean(){
		JndiObjectFactoryBean emfb = new JndiObjectFactoryBean();
		emfb.setJndiName("jdbc/adagioDS");
		return emfb;
	}
	
	/**
	 * 装配PersistenceExceptionTranslationPostProcessor的bean
	 * 这样@Repository注解产生的异常会转换成Spring的统一数据访问异常
	 * @return
	 */
	@Bean
	public BeanPostProcessor persistenceTranslation(){
		return new PersistenceExceptionTranslationPostProcessor();
	}
	
}
